package cn.maihe.elg.operation.schedule;

import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.maihe.elg.operation.model.vo.order.AcceptOrderDetailVO;
import cn.maihe.elg.operation.repository.entity.AcceptOrderInfoDO;
import cn.maihe.elg.operation.repository.entity.DecryptNoticeMsg;
import cn.maihe.elg.operation.repository.entity.DecryptNoticeMsgCondition;
import cn.maihe.elg.operation.service.order.AcceptOrderInfoService;
import cn.maihe.elg.operation.supports.sms.TencentCloudSmsService;
import cn.maihe.elg.operation.utils.IdGenerate;
import cn.maihe.framework.starter.mybatis.dao.MybatisDaoImpl;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;

/**
 * @Description 【补充需求信息】以投标截止时间后且开标时间前的项目，对已出函的投标企业经办人进行短信通知两次：投标截至时间后15分钟提醒1次，投标截至时间后30分钟提醒1次；
 * 【处理范围】针对已上线的省内外区域，先处理省内且订单多的，优先处理三明，处理时间排在宁德厦门国际银行-保函平台开发完后进行，【上线安排】与投标企业上送下发的内容同步上线；【需求目的】 是为了避免企业串标，需提醒投标企业在中心平台上传相关文件信息；请知晓！
 * @Author WJH
 * @Date 2021/08/10
 */

@Component
@Slf4j

public class DecryptNoticeMsgTask {

    private final AcceptOrderInfoService acceptOrderInfoService;
    private final AtomicBoolean running = new AtomicBoolean(false);

    @Resource
    private TencentCloudSmsService tencentCloudSmsService;

    public DecryptNoticeMsgTask(AcceptOrderInfoService acceptOrderInfoService) {
        this.acceptOrderInfoService = acceptOrderInfoService;
    }

    /**
     * 每分钟
     * 第一步打标记 已开函且未开标的订单的且decryptNoticeTime=0的订单，同时当前时间大于投标截止时间超过15min的打上decryptNoticeTime=1标记
     * 同时设置decryptNoticeDate=投标截止时间+decryptNoticeTime*15min，
     * <p>
     * 第二步，查询当前时间大于decryptNoticeDate的订单发起解密短信通知，若decryptNoticeTime=1为15min ，decryptNoticeTime=2为30min
     */
    @Scheduled(cron = "${cn.maihe.elg.operation.schedule.decryptNoticeCron}")
    public void decryptNoticeMsg() {
        if (running.compareAndSet(false, true)) {
            try {
                this.doFirstFlagDecryptNoticeTime();
                this.doSecondSendDecryptNoticeMsg();
            } catch (Exception e) {
                log.error("处理发送解密短信任务异常：{}", e.getMessage(), e);
            } finally {
                running.compareAndSet(true, false);
            }
        } else {
            log.info("处理发送解密短信任务已开启执行中，等待其结束后重试");
        }

    }

    /**
     * 每分钟
     * 第一步打标记 已开函且未开标的订单的且decryptNoticeTime=0的订单，同时当前时间大于投标截止时间超过15min的打上decryptNoticeTime=1标记
     * 同时设置decryptNoticeDate=投标截止时间+decryptNoticeTime*15min，
     * <p>
     * 第二步，查询当前时间大于decryptNoticeDate的订单发起解密短信通知，若decryptNoticeTime=1为15min ，decryptNoticeTime=2为30min
     */
    private void doFirstFlagDecryptNoticeTime() {
        try {
            Map<String, Object> params = new HashMap<>();
            params.put("curDate", Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant()));
            List<AcceptOrderDetailVO> list = acceptOrderInfoService.selectListBySql("selectFirstFlagDecryptNoticeTime", params);
            if (!CollectionUtils.isEmpty(list)) {
                List<DecryptNoticeMsg> msgList = new ArrayList<>(list.size());
                List<AcceptOrderInfoDO> updateList = list.stream().filter(o -> o.getDecryptNoticeTimes() == 0)
                        .map(o -> {
                            AcceptOrderInfoDO info = new AcceptOrderInfoDO();
                            info.setId(o.getId());
                            info.setDecryptNoticeTimes(1);
                            msgList.add(this.buildDecryptNoticeMsg(o));
                            return info;
                        }).collect(Collectors.toList());
                MybatisDaoImpl.run().updateBatchById(updateList, 1000);
                MybatisDaoImpl.run().insertBatch(msgList, 1000);
            }
        }catch (Exception e){
            log.error("标记解密短信任务异常:{}",e.getMessage(),e);
        }

    }

    private DecryptNoticeMsg buildDecryptNoticeMsg(AcceptOrderDetailVO o) {
        DecryptNoticeMsg decryptNoticeMsg = new DecryptNoticeMsg();
        decryptNoticeMsg.setId(IdGenerate.getId());
        decryptNoticeMsg.setAcceptOrderId(o.getId());
        decryptNoticeMsg.setAcceptOrderNo(o.getAcceptOrderNo());
        decryptNoticeMsg.setBidIndate(o.getBidIndate());
        decryptNoticeMsg.setBidOpenTime(o.getBidOpenTime());
        long betweenMinus = DateUtil.between(o.getBidIndate(),new Date(), DateUnit.MINUTE,false);
        if(betweenMinus>=0 && betweenMinus<=15){
            decryptNoticeMsg.setDecryptNoticeTimes(1);
            decryptNoticeMsg.setDecryptNoticeDate(Date.from(o.getBidIndate().toInstant().plus(15, ChronoUnit.MINUTES)));
        }else if(betweenMinus>15){
            decryptNoticeMsg.setDecryptNoticeTimes(2);
            decryptNoticeMsg.setDecryptNoticeDate(Date.from(o.getBidIndate().toInstant().plus(30, ChronoUnit.MINUTES)));
        }else{
            //负数不处理
            log.error("已过投标截止日期分钟数为[{}],暂不处理", betweenMinus);
        }
        decryptNoticeMsg.setProjectName(o.getProjectName());
        decryptNoticeMsg.setSectionName(o.getSectionName());
        decryptNoticeMsg.setBidderName(o.getBidderName());
        decryptNoticeMsg.setBidderContactTel(o.getBidderContactTel());
        return decryptNoticeMsg;
    }


    /**
     * 每分钟
     * 第一步打标记 已开函且未开标的订单的且decryptNoticeTime=0的订单，同时当前时间大于投标截止时间超过15min的打上decryptNoticeTime=1标记
     * 同时设置decryptNoticeDate=投标截止时间+decryptNoticeTime*15min，
     * <p>
     * 第二步，查询当前时间大于decryptNoticeDate的订单发起解密短信通知，若decryptNoticeTime=1为15min ，decryptNoticeTime=2为30min
     */
    private void doSecondSendDecryptNoticeMsg() {
        DecryptNoticeMsgCondition condition = DecryptNoticeMsgCondition.builder().andDecryptNoticeDateLt(new Date());
        List<DecryptNoticeMsg> list = MybatisDaoImpl.run().selectList(condition.build());
        if (!CollectionUtils.isEmpty(list)) {
            list.forEach(o -> {
                try {
                    if (o.getDecryptNoticeTimes() == 1) {
                        this.sendDecryptNoticeMsg(o.getBidderContactTel(), o.getProjectName(), "15分钟");
                        Date nextData = Date.from(o.getBidIndate().toInstant().plus(30, ChronoUnit.MINUTES));
                        o.setDecryptNoticeTimes(2);
                        o.setDecryptNoticeDate(nextData);
                        MybatisDaoImpl.run().updateById(o);
                        log.info("已发送15min后解密短信通知同时更新下次通知时间:{}", JSON.toJSONString(o));
                    }else
                    if (o.getDecryptNoticeTimes() == 2) {
                        this.sendDecryptNoticeMsg(o.getBidderContactTel(), o.getProjectName(), "30分钟");
                        log.info("已发送30min后解密短信通知同时删除该通知记录:{}", JSON.toJSONString(o));
                        MybatisDaoImpl.run().deleteById(DecryptNoticeMsg.class, o.getId());
                    } else {
                        //暂不处理
                    }
                } catch (Exception e) {
                    log.error("订单号：{} << 解密短信通知异常:{}  {}", o.getAcceptOrderNo(), e.getMessage(), JSON.toJSONString(o), e);
                }
            });
        }

    }

    private void sendDecryptNoticeMsg(String targetMobile, String projectName, String minute) {
        try {
            tencentCloudSmsService.sendDecryptNoticeMsg(targetMobile, projectName, minute);
        } catch (Exception e) {
            log.error("===发送短信={}--{}--{},异常：{}",targetMobile,projectName,minute,e.getMessage(), e);
        }
    }


}
